//A* 寻路算法 
cc.Class({
    extends: cc.Component,
    properties: {
        cost:1,  //每次移动花费
        mapSize:new cc.Size(0,0), //地图大小
        openList:null, //待考察列表
        closeList:null,  //已经考察列表
    },
    //创建一个节点
    crateNode:function(x,y){
        var node ={};
        node.x = x;
        node.y = y;
        //a* 参数
        node.g = 0; //当前节点到起始点的代价
        node.h = 0; //当前点到终点的代价
        node.f = 0; // f = g+h  
        if(!this.checkArray){
            node.canMove = 0;
        }else{
            node.canMove = this.checkArray[x][y]; //0:不能行走 1：可以行走 2：其他
        }
        //记录父节点 ，用来回溯路径
        node.father = null;
        return node 
    },

    //计算某点的估值函数(可以用其它实现)
    calculateH:function(point,endPoint){
        //距离的平方  这种有问题 会增大搜索量
        var x = Math.floor(endPoint.x-point.x);
        var y = Math.floor(endPoint.y-point.y);
        var dis = Math.abs(x)+Math.abs(y);
        return dis 
    },

    //判断某点是否在已经考察表内
    isClose:function(point){
        return this.findInList(point,this.openList)
    },
    //判断某点是否在待考察表内 
    isOpen:function(point){
        return this.findInList(point,this.openList)
    },
    //遍历数组 查看是否在列表内
    findInList:function(point,list){
        if(!list){
            return false;
        }
        for(var item in list){
            var pos = list[item];
            if(pos.x==point.x && pos.y==point.y){
                return true;
            }
        }
        return false;
    },

    //获取周围的点
    getRoundArray:function(point,mapSize){
        var around =new Array();
        //这里定义只能走上下左右 （如果需要其他方向的 在这里加 另外 斜着的花销应该比直线大 需要另外处理）
        if(point.y-1>=0){ //上面点
            around.push(this.crateNode(point.x,point.y-1))
        }
        if(point.y+1<mapSize.height){//下面点
            around.push(this.crateNode(point.x,point.y+1))
        }
        if(point.x-1>=0){//左
            around.push(this.crateNode(point.x-1,point.y))
        }
        if(point.x+1<mapSize.width){//右
            around.push(this.crateNode(point.x+1,point.y))
        }
        return around
    },

    //寻路逻辑
    //@startPos:起点
    //@endPos:终点
    //@mapSize:地图大小
    //@mapArray:寻路数组
    findPath:function(startPos,endPos,mapSize,mapArray){
        this.checkArray = mapArray;
        //初始化检查列表
        this.openList = new Array();
        this.closeList = new Array();

        //起始点
        var point = this.crateNode(startPos.x,startPos.y);
        point.g = 0;
        point.h = this.calculateH(point,endPos);
        point.f = point.g+point.h;
        //查找
        //当前节点不等于终点
        // console.log("起点：",startPos.toString(),"终点：",endPos.toString())
        while(!(point.x==endPos.x && point.y==endPos.y)){
            //根据类型 添加周围要查找的点
            // console.log("周围节点");
            var around = this.getRoundArray(point,mapSize);
            //检查周围点
            for(var key in around){
                var node = around[key];
                // console.log("check node：",node.x,node.y)
                if(this.isClose(node) || (node.canMove!=1&&node.canMove!=4)){//注意 对终点状态的屏蔽
                    //不可行走 或者已经查找
                    // console.log("不可以行走：",node.canMove)
                }else{
                    //计算此点的代价
                    var g = this.cost+point.g   //g值等同与上一步的G值+从上一步到这里的成本
                    var h = this.calculateH(node,endPos); 
                    var f = g+h; 

                    //该点不在open表内
                    if(!this.isOpen(node)){
                        node.g = g;
                        node.h = h;
                        node.f = f;
                        node.father = point;  //父节点
                        //添加到open表
                        this.openList.push(node);
                    }else{
                        //在open表内 则比较f值 
                        for(var key in this.openList){
                            var value = this.openList[key];
                            if(value.x == node.x && value.y == node.y){
                                //if(value.f>f)  //两种情况 比较g 或者f 值
                                if(value.g>g){
                                    value.f = f;
                                    value.g = g;
                                    value.h = h;
                                    value.father = point;   
                                }
                                break;
                            }
                        }
                    }
                }
            }
            //当前节点找完一遍 添加到close表
            this.closeList.push(point);

            // this.printTabal(this.openList);
            //open列表为空 则查找失败
            if(this.openList.length<=0){
                console.log("查找失败");
                return null;
            }

            //从open列表中去除最小的f点，并从open表中移除
            var max = null;
            var mykey = null;
            for(var key2 in this.openList){
                var nVal = this.openList[key2];
                if(!max ||nVal.f<max){
                    max = nVal.f;
                    mykey = key2; 
                }
            }
            //从open表中移除并去除最小f的点为起始点
            var removeArr = this.openList.splice(mykey,1);
            point = removeArr[0];
            // console.log("openList:",this.openList.toString())
            // console.log("最小点：",point.x,point.y);
        }
        //返回路径
        var path = new Array();
        while(point.father){
            path.push(cc.p(point.x,point.y));
            point = point.father;
        }
        return path
    },
});